#
# THIS IS MODULE LAUNCHER.PY
#

import os, sys, random
from globvars import *
import cPickle as pickle

def launchbuild(BUILD, prefdict, options, specifiedpd):
    print "*" * 40
    operadir = get_path_currentbuild(BUILD, prefdict)

    if operadir == None:
        from downloader import download_build
        operadir = download_build(BUILD, prefdict, options)

    # if we're just getting the file and not launching, it's about time
    # to pop out
    if options.get == True:
        sys.exit(0)
    

    os.chdir(operadir)
    
    if specifiedpd is not None:
        prefsdir = specifiedpd
    else:
        prefsdir = BUILD + '-' + str(random.randint(10000, 1000000))


    if int(BUILD) < 4158:
        launch = "./Opera -prefssuffix " + prefsdir
    else:
        launch = "./Opera -pd " + prefsdir

    
    print "Launching -+- %s" % (os.path.abspath("./Opera") + " -pd " + prefsdir)
    print "*" * 40

    os.system(launch)

# notice single quotes inserted in string, should maybe use \ ?

    # only clean up if the pd wasn't specified
    if specifiedpd is None:
        print "Cleaning up..."

        # TODO - make these use shutil.rmtree
    
        rmline = "rm -rf " + HOME + "/Library/Preferences/'Opera Preferences " + prefsdir + "'"
        os.system(rmline)

        rmline = "rm -rf " + HOME + "/Library/Application\ Support/'Opera " + prefsdir + "'"
        os.system(rmline)

        rmline = "rm -rf " + HOME + "/Library/Caches/'Opera " + prefsdir + "'"
        os.system(rmline)

    # TODO - figure out a clever way of actually returning something useful
    # this means we have to change all sys.exit-calls to returns, so that
    # we can receive them all the way down to the bottom of the stack
    return 0

# this function will load preferences and unpickle the object found
# in prefs file. if it doesn't find any file, it throws an IOError and
# returns 1. you are expected to catch this every time you call unpickle_prefs()
def unpickle_prefs():
    pref_file = HOME + "/.olprefs"

    try:
        file = open(pref_file, "r")
    except IOError:
        return 1
    try:
        prefdict = pickle.load(file)
    except UnpicklingError, info:
        print "Error %s unpickling preferences" % info
        print "Aborting..."
        sys.exit(1)
    file.close()
    return prefdict

# very crude function that opens the preferences file (overwrites every time),
# and dumps a pickled object into it
def pickle_prefs(prefdict):
    pref_file = HOME + "/.olprefs"
    
    try:
        file = open(pref_file, "w")
    except IOError, info:
        print "Error %s occurred while trying to write to ~/.olprefs" % info
        print "Aborting..."
        sys.exit(1)
    try:
        pickle.dump(prefdict, file)
    except PicklingError, info:
        print "Error %s occured while trying to pickle preferences" % info
        print "Aborting..."
        sys.exit(1)

    print "Saved preferences to ~/.olprefs"
            
    file.close()

# calls helperfunctions and loads preferences into a dictionary
def load_prefs():
    prefdict = unpickle_prefs()
    
    if prefdict == 1:
        raise
        # print "Could not find preferences file, aborting"
        # print "Please configure"
        # sys.exit(1)
    else:
        return prefdict


# this should be reused every time we need to go back to
# the "root" builddir


def get_path_currentbuild(buildno, prefdict, check=False):
    try:
        os.chdir(prefdict['builddir'])
    except:
        print "Directory %s doesn't seem to exist" % prefdict['builddir']
        print "Aborting..."
        sys.exit(1)
        
    FILELIST = os.listdir(os.curdir)
    print "Looking for build %s..." % (buildno)
    for entry in FILELIST:
	print entry
        if os.path.isdir(entry):
            if buildno in entry:
                operadir = os.path.abspath(entry) + PRESET
                print "Found it  -+- %s" % (operadir)
                if check is True:
                    sys.exit(0)

                return operadir
                break # eh, is this needed? God knows why its there.


def regtest(builds, buildlist, prefdict, options, specifiedpd, first):
    """
    builds = a list. first entry is startbuild, second entry is stopbuild
    current_build = which build we're launching this iteration
    buildlist = a list of available builds
    specifiedpd = if the user specified a pd, use it every time and don't delete it
    """
        
    # Make sure we have startbuild, stopbuild and current_build
    #print builds[0], builds[1], len(buildlist)
    
    if builds[1] == "":
        stopbuild = buildlist[-1:][0] # Last item
        #builds[1] = stopbuild
    else:
        stopbuild = builds[1]
    
    buildlist = [x for x in buildlist if x <= stopbuild]

    if builds[0] == "":
        startbuild = current_build = buildlist[0] # we want to start at the first build in this case
    else:
        startbuild = builds[0]
        buildlist = [x for x in buildlist if x >= startbuild]
        #print buildlist
        if first is True:
            current_build = buildlist[0]
        else:
            current_build = buildlist[len(buildlist)/2] # the one in the middle

    # If no builds are specified, we need some special logic to not fuck things up
    if builds[0] == builds[1] == "":
        launchbuild(current_build, prefdict, options, specifiedpd)
        print "Build %s quit. Did it (p)ass or (f)ail?" % current_build
        done = False
        while not done:
            result = raw_input() + " " # Pad it with a space in case the user inputs nothing
            if result[0].lower() == 'p':
                builds[0] = current_build
                done = True
            elif result[0].lower() == 'f':
                print "Failed in the first build available (build %s), so it's not a regression." % current_build
                sys.exit(0)
            else:
                print "Did build", current_build, "(p)ass or (f)ail?"
        regtest(builds, buildlist, prefdict, options, specifiedpd, first=False)

    print startbuild, stopbuild
     # remove builds above stopbuild and below startbuild
    
        
    # More than two builds left, keep trying
    if len(buildlist) > 2: 
        print "Launching build " + current_build
        
        launchbuild(current_build, prefdict, options, specifiedpd)

        print "Build %s quit. Did it (p)ass or (f)ail?" % current_build

        done = False

        while not done:
            result = raw_input() + " " # Pad it with a space in case the user inputs nothing
            if result[0].lower() == 'p':
                builds[0] = current_build # current build passes, so we don't want to test any higher
                done = True
            elif result[0].lower() == 'f':
                builds[1] = current_build # current build fails, so we don't want to test any lower
                done = True
            else:
                print "Did build", current_build, "(p)ass or (f)ail?"

        buildlist = [x for x in buildlist if x <= stopbuild]
        regtest(builds, buildlist, prefdict, options, specifiedpd, first=False)
        
    # No more builds to execute, we've got a result
    else:
        print "Regressed between builds", startbuild, "and", stopbuild
        
        
def list_builds(prefdict):

    try:
        os.chdir(prefdict['builddir'])
    except:
        print "Directory %s doesn't seem to exist" % prefdict['builddir']
        print "Aborting..."
        sys.exit(1)
    
    builds = os.listdir(os.curdir)
    builds.remove(".DS_Store")

    for i in range(0, len(builds)):
        builds[i] = builds[i].replace(".app", "")
    
    return builds
